# -*- coding:utf8 -*-
import json
import traceback
import os
import re
import base64
import typing
from scrapy import Request, FormRequest
from squirrel_core.commons.utils.tools import calc_str_md5, upload_file
from squirrel_core.frame.spider_makaka import MakakaSpider

file_path = os.environ.get("FILE_PATH", "/")


class racetiger_score(MakakaSpider):
    name = "racetiger_score"
    serialNumber = ""

    header = {
        "Host": "nc.racetigertiming.com",
        "Accept": "application/json, text/javascript, */*; q=0.01",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x63090c37) XWEB/14315 Flue",
        "X-Requested-With": "XMLHttpRequest"
    }
    captcha_url = "https://nc.racetigertiming.com/validate/captcha"
    athlete_url = "https://nc.racetigertiming.com/live/athlete"
    track_url = "https://nc.racetigertiming.com/live/track"
    cert_url = "https://rqs.racetigertiming.com/Result/Certificate"
    match_dict = {
        "2025崇礼云顶跑山赛（秋季赛）": "103754",
        "户外特工·2025第九届武功山越野赛": "103761",
        "2025额尔古纳河右岸湿地森林越野挑战赛": "103830",
        "2025第二届爽爽贵阳·天空之镜越野赛": "103785",
        "2025逐日者跑山训练赛-北京·模式口站": "104014",
        "2025贵阳·清镇半程马拉松": "104019",
        "2025遂宁观音湖马拉松": "104161"
    }

    def get_ext_requests_or_urls(self, data=None):
        if data and isinstance(data, str):
            data = json.loads(data)
        if data and isinstance(data, typing.MutableMapping):
            self.serialNumber = data.get("serialNumber", "")
            race_id = data.get("spider_config", {}).get("race_id", "")
            user_id = data.get("spider_config", {}).get("user_id", "")
            race_no = data.get("spider_config", {}).get("race_no", "")
            user_name = data.get("spider_config", {}).get("user_name", "")
            race_name = data.get("spider_config", {}).get("race_name", "").replace(" ", "")
            home_url = data.get("spider_config", {}).get("url", "")
            card_num = data.get("spider_config", {}).get("card_num", "")
            if not user_name and not race_no:
                self.logger.info("user_name和card_num必须存在一个")
                self.upload_procedure({"serialNumber": self.serialNumber, "code": 101, "message": "user_name和card_num必须存在一个"})
                self.close_after_idle = True
                self.force_to_close_spider = True
            else:
                self.upload_procedure({"serialNumber": self.serialNumber, "code": 100, "message": "任务启动成功"})
                _id = "".join(re.findall(r"id=(.*)&", home_url)).strip()
                _race_id = self.match_dict.get(race_name, "")
                header = {
                    "Host": "rqs.racetigertiming.com",
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0",
                    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
                    "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
                    "Accept-Encoding": "gzip, deflate, br, zstd",
                    "Content-Type": "application/x-www-form-urlencoded"
                }
                url = f"https://rqs.racetigertiming.com/Result/Query/{_id}?raceId={_race_id}"
                if "崇礼云顶" in race_name:
                    data = {"qRaceId": _race_id, "qID": _id, "dbt": "", "memberId": race_no}
                else:
                    data = {"qRaceId": _race_id, "qID": _id, "dbt": "", "athleteName": user_name, "idNumber": card_num}
                yield FormRequest(url=url, callback=self.parse_score, dont_filter=True, errback=self.err_parse,
                                  formdata=data,
                                  headers=header,
                                  meta={"race_id": race_id, "user_id": user_id, "race_no": race_no,
                                        "user_name": user_name, "race_name": race_name, "_race_id": _race_id,
                                        "card_num": card_num, "_id": _id, "home_url": home_url})

    def parse_score(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        _race_id = response.meta.get("_race_id", "")
        _id = response.meta.get("_id", "")
        race_name = response.meta.get("race_name", "")
        user_name = response.meta.get("user_name", "")
        card_num = response.meta.get("card_num", "")
        home_url = response.meta.get("home_url", "")
        try:
            self.logger.info(f"开始查找{race_no}的净成绩:{response.url}")
            title_list = response.xpath("//li[@class='mui-table-view-cell']/div[@class='mui-pull-left']/text()").extract()
            title_list = [title.strip() for title in title_list]
            value_value = response.xpath("//li[@class='mui-table-view-cell']/div[@class='mui-pull-right']/text()").extract()
            score_dict = dict(zip(title_list, value_value))
            if score_dict:
                score_info = []
                tr_list =response.xpath("//table[@id='gradetbl']/tbody/tr")
                for tr in tr_list:
                    td_list = tr.xpath("./td/text()").extract()
                    td_list = [td.strip() for td in td_list]
                    cp_name = td_list[0]
                    start_time = td_list[1]
                    stop_time = td_list[-1]
                    cp_length = ""
                    speed = ""
                    score_info.append({"cp_name": cp_name, "start_time": start_time, "score": stop_time, "distance": cp_length, "pace": speed})
                if score_info:
                    score_info[-1]["cp_name"] = "FINISH"

                score_data = {"race_name": race_name, "itemName": score_dict.get("参赛项目", ""), "name": score_dict.get("姓名", ""),
                              "raceNo": race_no, "distance": score_dict.get("参赛项目", "").replace("组", ""),
                              "shotScore": score_dict.get("枪时成绩", ""), "score": score_dict.get("净时成绩", ""),
                              "sectionScore": score_info}
                event_id = "".join(re.findall(r"eventId.value = '(.*)'", response.text)) or "1"
                athelet_id = "".join(re.findall(r"atheletID.value = '(.*)'", response.text)) or "24"
                if score_data["score"]:
                    boundary = "geckoformboundary39befe98372d32c7256f62286f7581d"
                    if "武功山越野赛" in race_name:
                        boundary = "WebKitFormBoundaryu8LZKPQ27x4jAgWa"
                    if "遂宁观音湖马拉松" in race_name:
                        boundary = "WebKitFormBoundary0wl5dLEeY9joxlQD"
                    cert_header = {
                        'Content-Type': f'multipart/form-data; boundary=----{boundary}',
                        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
                    }
                    body = f"""------{boundary}\r
Content-Disposition: form-data; name="memberId"\r
\r
{race_no}\r
------{boundary}\r
Content-Disposition: form-data; name="raceId"\r
\r
{_race_id}\r
------{boundary}\r
Content-Disposition: form-data; name="eventId"\r
\r
{event_id}\r
------{boundary}\r
Content-Disposition: form-data; name="atheletId"\r
\r
{athelet_id}\r
------{boundary}\r
Content-Disposition: form-data; name="dbt"\r
\r
1\r
------{boundary}\r
Content-Disposition: form-data; name="photoData"\r
\r
\r
------{boundary}--"""

                    yield Request(url=self.cert_url, callback=self.parse_pic, dont_filter=True, errback=self.err_parse,
                                  body=body,
                                  method="POST", headers=cert_header,
                                  meta={"race_id": race_id, "user_id": user_id, "score_data": score_data,
                                        "race_no": race_no, "handle_httpstatus_list": [500]})
                else:
                    result = self.result_item_assembler(response)
                    result['result_data'] = {"serialNumber": self.serialNumber, "webType": self.name_first,
                                             "crawlerType": self.name_second, "data": str(score_data)}
                    yield result
            else:
                partner = "".join(re.findall(r"partner=(.*?)(?:&|$)", home_url)).strip()
                _id = "".join(re.findall(r"id=(.*?)&", home_url)).strip()
                yield Request(url=home_url, callback=self.parse, dont_filter=True, errback=self.err_parse,
                              headers=self.header, meta={"race_id": race_id, "user_id": user_id, "race_no": race_no,
                                                         "user_name": user_name, "race_name": race_name,
                                                         "partner": partner,
                                                         "card_num": card_num, "_id": _id})

        except Exception:
            self.logger.info(f"查找{race_no}的净成绩时出错{response.url}：{traceback.format_exc()}")

    def parse_pic(self, response):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        score_data = response.meta.get("score_data", {})
        try:
            self.logger.info(f"开始下载{race_no}的证书：{response.url}")
            pic_md5 = calc_str_md5(response.url)
            pic_name = f"{race_no}_{pic_md5}.jpg"
            dir_path = os.path.join(file_path, "picture", self.name_first)
            if not os.path.exists(dir_path):
                os.makedirs(dir_path)
            save_path = os.path.join(dir_path, pic_name)
            img_base64 = response.xpath("//img[@id='certifImg']/@src").extract_first()
            if ',' in img_base64:
                base64_string = img_base64.split(',')[1]
                if not os.path.exists(save_path):
                    with open(save_path, "wb") as f:
                        f.write(base64.b64decode(base64_string))
                    upload_path = f"flow/{race_id}/{user_id}/pic/{pic_name}"
                    upload_flag = upload_file(save_path, upload_path)
                    if upload_flag:
                        self.logger.info(f"{save_path}上传成功：{upload_path}")
                    else:
                        self.logger.info(f"{save_path}上传失败：{upload_path}")
                    score_data["certImg"] = upload_path
        except Exception:
            self.logger.info(f"下载{race_no}证书时出错{response.url}：{traceback.format_exc()}")
        finally:
            result = self.result_item_assembler(response)
            result['result_data'] = {"serialNumber": self.serialNumber, "webType": self.name_first,
                                     "crawlerType": self.name_second, "data": str(score_data)}
            yield result

    def parse(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        race_name = response.meta.get("race_name", "")
        user_name = response.meta.get("user_name", "")
        partner = response.meta.get("partner", "")
        card_num = response.meta.get("card_num", "")
        _id = response.meta.get("_id", "")
        try:
            self.logger.info(f"开始查找{race_no}的_race_id:{response.url}")

            _race_id = response.xpath("//input[@id='race_id']/@value").extract_first()
            group_list = []
            buttons = response.xpath("//button[contains(@id, 'event_')]")
            for button in buttons:
                group_name = button.xpath("./text()").extract_first()
                group_id = button.xpath("./@onclick").extract_first().replace("qryEventList('", "").replace("')",
                                                                                                            "")
                group_list.append((group_name, group_id))
            if group_list:
                group_name, group_id = group_list.pop(0)
                yield Request(url=self.captcha_url, callback=self.parse_token, dont_filter=True,
                              errback=self.err_parse,
                              headers=self.header, meta={"race_id": race_id, "user_id": user_id, "race_no": race_no,
                                                         "race_item": group_name,
                                                         "user_name": user_name, "race_name": race_name,
                                                         "_race_id": _race_id, "_id": _id,
                                                         "event_id": group_id, "partner": partner,
                                                         "card_num": card_num, "group_list": group_list})

        except Exception:
            self.logger.info(f"查找{race_no}的_race_id时出错{response.url}：{traceback.format_exc()}")

    def parse_token(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        race_name = response.meta.get("race_name", "")
        user_name = response.meta.get("user_name", "")
        _race_id = response.meta.get("_race_id", "")
        event_id = response.meta.get("event_id", "")
        partner = response.meta.get("partner", "")
        card_num = response.meta.get("card_num", "")
        race_item = response.meta.get("race_item", "")
        _id = response.meta.get("_id", "")
        group_list = response.meta.get("group_list", [])
        try:
            self.logger.info(f"开始查找{race_no}的token:{response.url}")
            token = json.loads(response.text).get("obj", {}).get("token", "")
            post_data = {"partner": partner, "raceId": _race_id, "eventId": event_id,
                         "token": token, "captcha": "", "bib": race_no, "name": ""}
            yield FormRequest(url=self.athlete_url, callback=self.parse_base_score, dont_filter=True,
                              errback=self.err_parse,
                              formdata=post_data, headers=self.header,
                              meta={"race_id": race_id, "user_id": user_id, "race_no": race_no,
                                    "race_item": race_item, "event_id": event_id, "group_list": group_list,
                                    "user_name": user_name, "race_name": race_name, "_race_id": _race_id,
                                    "partner": partner, "card_num": card_num, "_id": _id})

        except Exception:
            self.logger.info(f"查找{race_no}的token时出错{response.url}：{traceback.format_exc()}")

    def parse_base_score(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        race_name = response.meta.get("race_name", "")
        user_name = response.meta.get("user_name", "")
        _race_id = response.meta.get("_race_id", "")
        partner = response.meta.get("partner", "")
        card_num = response.meta.get("card_num", "")
        _id = response.meta.get("_id", "")
        race_item = response.meta.get("race_item", "")
        group_list = response.meta.get("group_list", [])
        try:
            if '枪时成绩' in response.text:
                self.logger.info(f"开始解析{race_no}的基本成绩:{response.url}")
                shot_score = ""
                score = ""
                div_list = response.xpath("//div[@class='style-info-msg']/div")
                for div in div_list:
                    value = div.xpath("./text()").extract_first()
                    if "枪时成绩" in value:
                        shot_score = value.replace("枪时成绩：", "")
                    if "净时成绩" in value:
                        score = value.replace("净时成绩：", "")
                score_data = {"race_name": race_name, "itemName": race_item, "name": user_name, "raceNo": race_no,
                              "distance": race_item.replace("组", ""), "shotScore": shot_score, "score": score}
                post_data = {"partner": partner, "raceId": _race_id, "name": user_name, "bib": race_no}
                yield FormRequest(url=self.track_url, callback=self.parse_detail_score, dont_filter=True,
                                  errback=self.err_parse,
                                  formdata=post_data, headers=self.header,
                                  meta={"race_id": race_id, "user_id": user_id, "race_item": race_item,
                                        "race_no": race_no,
                                        "user_name": user_name, "race_name": race_name, "_race_id": _race_id,
                                        "score_data": score_data, "card_num": card_num, "_id": _id})
            else:
                self.logger.info(f'开始请求:{response.meta.get("race_item", "")}')
                if group_list:
                    group_name, group_id = group_list.pop(0)
                    yield Request(url=self.captcha_url, callback=self.parse_token, dont_filter=True,
                                  errback=self.err_parse,
                                  headers=self.header,
                                  meta={"race_id": race_id, "user_id": user_id, "race_no": race_no,
                                        "race_item": group_name,
                                        "user_name": user_name, "race_name": race_name, "_race_id": _race_id,
                                        "_id": _id,
                                        "event_id": group_id, "partner": partner, "card_num": card_num,
                                        "group_list": group_list})
        except Exception:
            self.logger.info(f"查找{race_no}的基本成绩时出错{response.url}：{traceback.format_exc()}")

    def parse_detail_score(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        race_name = response.meta.get("race_name", "")
        user_name = response.meta.get("user_name", "")
        _race_id = response.meta.get("_race_id", "")
        card_num = response.meta.get("card_num", "")
        _id = response.meta.get("_id", "")
        score_data = response.meta.get("score_data", {})
        try:
            self.logger.info(f"开始查找{race_no}的分段成绩:{response.url}")
            score_info = []
            data_list = json.loads(response.text).get("obj", [])
            for data in data_list:
                cp_name = data[0].get("fieldValue", "")
                start_time = data[1].get("fieldValue", "").split(".")[1].strip() if "." in data[1].get("fieldValue",
                                                                                                       "") else \
                data[1].get("fieldValue", "")
                stop_time = data[2].get("fieldValue", "")
                cp_length = ""
                speed = ""
                score_info.append(
                    {"cp_name": cp_name, "start_time": start_time, "score": stop_time, "distance": cp_length,
                     "pace": speed})
            if score_info:
                score_info[-1]["cp_name"] = "FINISH"
            score_data["sectionScore"] = score_info

            score_data["certImg"] = ""
            header = {
                "Host": "rqs.racetigertiming.com",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0",
                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
                "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
                "Accept-Encoding": "gzip, deflate, br, zstd",
                "Content-Type": "application/x-www-form-urlencoded"
            }
            url = f"https://rqs.racetigertiming.com/Result/Query/{_id}?raceId={_race_id}"
            data = {"qRaceId": _race_id, "qID": _id, "dbt": "", "memberId": race_no}
            if "武功山越野赛" in race_name:
                data = {"qRaceId": _race_id, "qID": _id, "dbt": "", "athleteName": user_name,
                        "idNumber": card_num}
            yield FormRequest(url=url, callback=self.parse_score1, dont_filter=True, errback=self.err_parse,
                              formdata=data,
                              headers=header,
                              meta={"race_id": race_id, "user_id": user_id, "race_no": race_no,
                                    "user_name": user_name, "race_name": race_name, "_race_id": _race_id,
                                    "score_data": score_data, "card_num": card_num, "_id": _id})
        except Exception:
            self.logger.info(f"查找{race_no}的分段成绩时出错{response.url}：{traceback.format_exc()}")

    def parse_score1(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        _race_id = response.meta.get("_race_id", "")
        _id = response.meta.get("_id", "")
        race_name = response.meta.get("race_name", "")
        score_data = response.meta.get("score_data", {})
        try:
            self.logger.info(f"开始查找{race_no}的净成绩:{response.url}")
            title_list = response.xpath(
                "//li[@class='mui-table-view-cell']/div[@class='mui-pull-left']/text()").extract()
            title_list = [title.strip() for title in title_list]
            value_value = response.xpath(
                "//li[@class='mui-table-view-cell']/div[@class='mui-pull-right']/text()").extract()
            score_dict = dict(zip(title_list, value_value))
            score_data["score"] = score_dict.pop("净时成绩", "")
            result = self.result_item_assembler(response)
            result['result_data'] = {"serialNumber": self.serialNumber, "webType": self.name_first,
                                     "crawlerType": self.name_second, "data": str(score_data)}
            yield result

        except Exception:
            self.logger.info(f"查找{race_no}的净成绩时出错{response.url}：{traceback.format_exc()}")

    def err_parse(self, failure):
        self.logger.warning(f"请求失败：{failure.request.url},错误原因:{traceback.format_exc()}")

